feat(input): 新增统一输入抽象与Godot集成#346
Conversation
- 新增输入绑定 DTO、设备上下文和 UI 语义桥接契约。 - 实现 Game 默认输入绑定存储、动作映射和 UI 分发桥接。 - 落地 Godot InputMap 适配、测试覆盖与配套文档。 - 更新 ai-plan 恢复点、worktree 映射与采用入口。
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthrough新增输入抽象与 DTO(动作绑定、描述符、快照、设备上下文、枚举、接口),在 Game 层实现托管 InputBindingStore、设备追踪与 UI 映射/分发;在 Godot 层新增编解码器、InputMap 后端适配与 GodotInputBindingStore;附带单元测试与中文文档。 变更输入系统完整实现
预计代码审查工作量🎯 4 (复杂) | ⏱️ ~50 分钟 可能相关的 PR
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Test ResultsDetails
Insights
build-and-test: Run #1102
🎉 All tests passed!Slowest Tests
🎉 No failed tests in this run. | 🍂 No flaky tests in this run. Github Test Reporter by CTRF 💚 |
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| dotnet-format | yes | 1 | no | 4.93s | ||
| ✅ REPOSITORY | gitleaks | yes | no | no | 8.27s | |
| ✅ REPOSITORY | trufflehog | yes | no | no | 7.08s |
Detailed Issues
⚠️ CSHARP / dotnet-format - 1 error
Welcome to .NET 9.0!
---------------------
SDK Version: 9.0.114
----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https
----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
Unhandled exception: System.Exception: Restore operation failed.
at Microsoft.CodeAnalysis.Tools.CodeFormatter.OpenMSBuildWorkspaceAsync(String solutionOrProjectPath, WorkspaceType workspaceType, Boolean noRestore, Boolean requiresSemantics, String binaryLogPath, Boolean logWorkspaceWarnings, ILogger logger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Tools.CodeFormatter.FormatWorkspaceAsync(FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken, String binaryLogPath)
at Microsoft.CodeAnalysis.Tools.FormatCommandCommon.FormatAsync(FormatOptions formatOptions, ILogger`1 logger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Tools.Commands.RootFormatCommand.FormatCommandDefaultHandler.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
at System.CommandLine.Invocation.InvocationPipeline.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
See detailed reports in MegaLinter artifacts
Set VALIDATE_ALL_CODEBASE: true in mega-linter.yml to validate all sources, not only the diff

Show us your support by starring ⭐ the repository
|
| Filename | Overview |
|---|---|
| GFramework.Game/Input/InputBindingStore.cs | Correct in-memory implementation with clear/replace ImportSnapshot, conflict-swap SetPrimaryBinding, and thread-safety disclaimer in remarks. |
| GFramework.Godot/Input/GodotInputBindingStore.cs | Godot adapter that now correctly handles the full-replace ImportSnapshot contract; every public call reloads from the backend first. |
| GFramework.Godot/Input/GodotInputBindingCodec.cs | Bidirectional codec is well-structured; the TryCreateBinding out parameter uses a null-forgiving suppression (null!) that could be resolved by declaring it as nullable. |
| GFramework.Godot/Input/GodotInputMapBackend.cs | Correctly captures defaults at construction, restores via SetBindings (which handles missing actions), and erases non-default actions on reset. |
| GFramework.Game.Tests/Input/InputBindingStoreTests.cs | Covers SetPrimaryBinding swap, ResetAll, and GetBindings; ImportSnapshot and ResetAction paths are not tested for InputBindingStore directly. |
| GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.cs | Good FakeInputMapBackend design; covers ImportSnapshot, SetPrimaryBinding swap, and ResetAll; ResetAction on GodotInputBindingStore is not covered. |
Sequence Diagram
sequenceDiagram
participant Host as Godot Host
participant GIS as GodotInputBindingStore
participant State as InputBindingStore
participant Backend as IGodotInputMapBackend
participant InputMap as Godot InputMap
Note over GIS,InputMap: Construction
GIS->>Backend: GetActionNames()
Backend->>InputMap: InputMap.GetActions()
InputMap-->>Backend: actions[]
GIS->>Backend: GetBindings(each action)
Backend->>InputMap: InputMap.ActionGetEvents()
GIS->>GodotInputBindingCodec: TryCreateBinding(inputEvent)
GodotInputBindingCodec-->>GIS: InputBindingDescriptor
GIS->>State: new InputBindingStore(snapshot)
Note over GIS,InputMap: SetPrimaryBinding
Host->>GIS: SetPrimaryBinding(action, binding)
GIS->>Backend: ReloadFromBackend
GIS->>State: SetPrimaryBinding(action, binding)
GIS->>State: ExportSnapshot()
State-->>GIS: snapshot
GIS->>Backend: SetBindings(each action)
Backend->>InputMap: ActionEraseEvents + ActionAddEvent
Note over GIS,InputMap: ImportSnapshot
Host->>GIS: ImportSnapshot(snapshot)
GIS->>Backend: ReloadFromBackend
GIS->>State: ExportSnapshot to compute removedActions
GIS->>Backend: SetBindings(removedAction, [])
GIS->>Backend: SetBindings(each snapshot action)
GIS->>Backend: ReloadFromBackend final sync
Note over GIS,InputMap: ResetAll
Host->>GIS: ResetAll()
GIS->>Backend: ResetAll()
Backend->>InputMap: EraseAction or ActionEraseEvents+AddEvent
GIS->>Backend: ReloadFromBackend
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
GFramework.Game.Tests/Input/InputBindingStoreTests.cs:13-14
**Missing test coverage for `ImportSnapshot` and `ResetAction` on `InputBindingStore`**
AGENTS.md requires that "when a public API defines multiple contract branches, tests MUST cover the meaningful variants." `InputBindingStore` exposes six public methods; only three are exercised here (`SetPrimaryBinding`, `ResetAll`, `GetBindings`). Both `ImportSnapshot` (clear-and-replace semantics) and `ResetAction` (single-action rollback) have distinct internal paths that should be independently verified. The same gap exists in `GodotInputBindingStoreTests`, where `ResetAction` on the `GodotInputBindingStore` is never called.
### Issue 2 of 3
GFramework.Godot/Input/GodotInputBindingCodec.cs:20
AGENTS.md requires null-safe code that respects nullable annotations instead of suppressing warnings. The null-forgiving operator on the `out` parameter is technically safe here because callers check the `bool` return value, but it bypasses the compiler's nullability flow. Declaring the out parameter as `InputBindingDescriptor?` makes the contract explicit and avoids the suppression entirely.
```suggestion
public static bool TryCreateBinding(InputEvent inputEvent, out InputBindingDescriptor? binding)
```
### Issue 3 of 3
GFramework.Godot/Input/GodotInputBindingCodec.cs:57-59
When the `out` parameter is typed as nullable, the null-forgiving suppression on the default branch can be removed cleanly.
```suggestion
default:
binding = null;
return false;
```
Reviews (3): Last reviewed commit: "fix(input): 修复输入绑定重置与审查遗留问题" | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (6)
GFramework.Game.Abstractions/Input/InputBindingSnapshot.cs (1)
9-23: ⚡ Quick win建议考虑使用 record 类型
InputBindingSnapshot是可持久化快照的值对象,表示整个绑定配置的不可变视图。建议改为record类型以获得值语义,便于快照比较和序列化场景。♻️ 建议的 record 重构
/// <summary> /// 描述一组动作绑定的可持久化快照。 /// </summary> -public sealed class InputBindingSnapshot +public sealed record InputBindingSnapshot { - /// <summary> - /// 初始化一个输入绑定快照。 - /// </summary> - /// <param name="actions">动作绑定集合。</param> public InputBindingSnapshot(IReadOnlyList<InputActionBinding> actions) { Actions = actions ?? Array.Empty<InputActionBinding>(); } - /// <summary> - /// 获取动作绑定集合。 - /// </summary> - public IReadOnlyList<InputActionBinding> Actions { get; } + public IReadOnlyList<InputActionBinding> Actions { get; init; } }注意:record 仍需保留 XML 文档注释。如果快照会被序列化(例如保存到配置文件),record 的
ToString()输出也会更便于调试。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Game.Abstractions/Input/InputBindingSnapshot.cs` around lines 9 - 23, Replace the class InputBindingSnapshot with a record to give it value semantics: change the declaration to a record type named InputBindingSnapshot while preserving the existing XML documentation comments; ensure the Actions property remains an IReadOnlyList<InputActionBinding> and that the constructor logic (or primary constructor) still defaults null to Array.Empty<InputActionBinding>() so existing behavior and immutability are preserved; keep the public API (type name and property) unchanged so comparisons and serialization benefit from record semantics.GFramework.Godot/Input/IGodotInputMapBackend.cs (1)
11-43: 💤 Low value接口契约清晰,建议明确前置条件
接口方法的参数和返回值类型合理,使用
IReadOnlyList保持了不可变性契约。作为可选改进,建议在 XML 文档中明确关键方法的前置条件(例如actionName不能为null),以便实现者和调用者了解验证责任归属。📝 建议的文档增强示例
/// <summary> /// 获取指定动作的框架绑定描述集合。 /// </summary> -/// <param name="actionName">动作名称。</param> +/// <param name="actionName">动作名称,不能为 <see langword="null" />。</param> /// <returns>框架绑定描述集合。</returns> +/// <exception cref="ArgumentNullException">当 <paramref name="actionName" /> 为 <see langword="null" /> 时抛出。</exception> IReadOnlyList<InputBindingDescriptor> GetBindings(string actionName);类似地为
SetBindings、ResetAction等方法添加前置条件说明。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Godot/Input/IGodotInputMapBackend.cs` around lines 11 - 43, Add clear precondition docs to the interface: state that actionName for GetBindings, SetBindings, ResetAction must be non-null and non-empty and that SetBindings' bindings parameter must be non-null (and may be empty) and that GetActionNames/ GetBindings return IReadOnlyList that will never be null; also specify whether implementations should throw ArgumentNullException/ArgumentException on violation or silently ignore—e.g., document to throw ArgumentNullException for null actionName and ArgumentException for empty names, and ArgumentNullException for null bindings in SetBindings. Update the XML comments for GetBindings, SetBindings, ResetAction, and ResetAll to include these precondition sentences and the expected exceptions so implementers and callers know validation responsibility.GFramework.Game.Abstractions/Input/InputDeviceContext.cs (1)
9-25: ⚡ Quick win建议考虑使用 record 类型
InputDeviceContext是一个不可变的值对象,包含设备上下文快照数据。考虑将其改为record类型以获得内置的值语义(Equals、GetHashCode、ToString),这在设备上下文比较或调试时会更便利。♻️ 建议的 record 重构
/// <summary> /// 描述当前活跃输入设备上下文。 /// </summary> -public sealed class InputDeviceContext +public sealed record InputDeviceContext { - /// <summary> - /// 初始化一个输入设备上下文。 - /// </summary> - /// <param name="deviceKind">当前设备族。</param> - /// <param name="deviceIndex">设备索引;未知时为 <see langword="null" />。</param> - /// <param name="deviceName">宿主归一化后的设备名称。</param> - public InputDeviceContext( + public InputDeviceContext( InputDeviceKind deviceKind, int? deviceIndex = null, string? deviceName = null) { DeviceKind = deviceKind; DeviceIndex = deviceIndex; DeviceName = deviceName ?? string.Empty; } - /// <summary> - /// 获取当前设备族。 - /// </summary> - public InputDeviceKind DeviceKind { get; } + public InputDeviceKind DeviceKind { get; init; } - /// <summary> - /// 获取当前设备索引。 - /// </summary> - public int? DeviceIndex { get; } + public int? DeviceIndex { get; init; } - /// <summary> - /// 获取宿主归一化后的设备名称。 - /// </summary> - public string DeviceName { get; } + public string DeviceName { get; init; } }注意:改为 record 后仍需保留 XML 文档注释(record 的属性和构造函数参数),以符合编码规范。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Game.Abstractions/Input/InputDeviceContext.cs` around lines 9 - 25, InputDeviceContext is an immutable value object so change the class to a record to get value semantics; replace the sealed class declaration with a record (e.g., record InputDeviceContext) and expose the same data via init-only properties or a positional record matching the existing constructor parameters (DeviceKind, int? DeviceIndex, string? DeviceName) while preserving the XML documentation comments for the constructor/parameters and retaining the DeviceKind, DeviceIndex and DeviceName identifiers and null-handling (DeviceName defaulting to string.Empty) so Equals/GetHashCode/ToString behave as value semantics.GFramework.Game.Abstractions/Input/InputBindingDescriptor.cs (1)
13-41: ⚡ Quick win建议考虑使用 record 类型
InputBindingDescriptor是不可变的数据传输对象,包含绑定描述快照。与InputDeviceContext类似,建议改为record类型以获得值语义,便于相等性比较和调试输出。♻️ 建议的 record 重构
/// <summary> /// 描述一个框架无关的动作绑定。 /// </summary> /// <remarks> /// 该模型是运行时输入系统与宿主适配层之间的稳定交换格式。 /// 宿主层负责把原生输入事件转成此描述,抽象层和默认运行时只根据这些字段做查询、冲突检测和持久化。 /// </remarks> -public sealed class InputBindingDescriptor +public sealed record InputBindingDescriptor { - /// <summary> - /// 初始化一个动作绑定描述。 - /// </summary> - /// <param name="deviceKind">设备族。</param> - /// <param name="bindingKind">绑定类型。</param> - /// <param name="code">宿主无关的物理码值。</param> - /// <param name="displayName">用于设置界面展示的名称。</param> - /// <param name="axisDirection">轴向方向;非轴向绑定时为 <see langword="null" />。</param> - /// <exception cref="ArgumentException">当 <paramref name="code" /> 为空时抛出。</exception> public InputBindingDescriptor( InputDeviceKind deviceKind, InputBindingKind bindingKind, string code, string displayName, float? axisDirection = null) { if (string.IsNullOrWhiteSpace(code)) { throw new ArgumentException("Binding code cannot be null or whitespace.", nameof(code)); } DeviceKind = deviceKind; BindingKind = bindingKind; Code = code; DisplayName = displayName ?? string.Empty; AxisDirection = axisDirection; } - /// <summary> - /// 获取设备族。 - /// </summary> - public InputDeviceKind DeviceKind { get; } + public InputDeviceKind DeviceKind { get; init; } - /// <summary> - /// 获取绑定类型。 - /// </summary> - public InputBindingKind BindingKind { get; } + public InputBindingKind BindingKind { get; init; } - /// <summary> - /// 获取宿主无关的物理码值。 - /// </summary> - public string Code { get; } + public string Code { get; init; } - /// <summary> - /// 获取用于展示的标签。 - /// </summary> - public string DisplayName { get; } + public string DisplayName { get; init; } - /// <summary> - /// 获取轴向方向。 - /// </summary> - public float? AxisDirection { get; } + public float? AxisDirection { get; init; } }注意:record 仍需保留 XML 文档注释以符合编码规范。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Game.Abstractions/Input/InputBindingDescriptor.cs` around lines 13 - 41, Convert the immutable data class InputBindingDescriptor into a record with the same public API: change InputBindingDescriptor to a public sealed record that exposes DeviceKind, BindingKind, Code, DisplayName and AxisDirection as init-only properties (or positional parameters) while preserving the constructor validation that throws ArgumentException when Code is null/whitespace, preserve the default DisplayName -> string.Empty and nullable AxisDirection behavior, and keep the existing XML doc comments; ensure equality/value semantics and ToString come from the record type and that any callers using the old constructor still get the validation logic.GFramework.Game.Abstractions/Input/InputActionBinding.cs (1)
9-26: ⚡ Quick win建议考虑使用 record 类型
InputActionBinding是不可变快照类型,表示动作及其绑定的只读视图。建议改为record以获得值语义,与其他快照类型(如InputBindingSnapshot)保持一致的设计模式。♻️ 建议的 record 重构
/// <summary> /// 描述一个逻辑动作当前持有的绑定集合。 /// </summary> -public sealed class InputActionBinding +public sealed record InputActionBinding { - /// <summary> - /// 初始化一个动作绑定快照。 - /// </summary> - /// <param name="actionName">动作名称。</param> - /// <param name="bindings">当前绑定列表。</param> - /// <exception cref="ArgumentException">当 <paramref name="actionName" /> 为空时抛出。</exception> public InputActionBinding(string actionName, IReadOnlyList<InputBindingDescriptor> bindings) { if (string.IsNullOrWhiteSpace(actionName)) { throw new ArgumentException("Action name cannot be null or whitespace.", nameof(actionName)); } ActionName = actionName; Bindings = bindings ?? Array.Empty<InputBindingDescriptor>(); } - /// <summary> - /// 获取动作名称。 - /// </summary> - public string ActionName { get; } + public string ActionName { get; init; } - /// <summary> - /// 获取当前绑定列表。 - /// </summary> - public IReadOnlyList<InputBindingDescriptor> Bindings { get; } + public IReadOnlyList<InputBindingDescriptor> Bindings { get; init; } }注意:record 仍需保留 XML 文档注释。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Game.Abstractions/Input/InputActionBinding.cs` around lines 9 - 26, Convert the immutable snapshot class InputActionBinding to a record to get value semantics consistent with other snapshots (e.g., InputBindingSnapshot): change the declaration from class to a record (e.g., public sealed record InputActionBinding) and keep the existing constructor logic that validates actionName and assigns Bindings (falling back to Array.Empty<InputBindingDescriptor>() when null); preserve the XML doc comments for the type and parameters, and ensure the public members ActionName and Bindings remain available (init-only or positional record properties) so existing callers continue to work.ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md (1)
7-8: ⚡ Quick win收敛 trace 中的环境路径细节
这里记录本地 worktree 目录名对恢复入口帮助不大,且会把环境细节带进公开历史。建议改为“分支名 + PR 编号”这类稳定标识。
As per coding guidelines "Never write ... machine usernames, home-directory paths ... or other sensitive environment details into any
ai-plan/**file" and "Never record absolute file-system paths inai-plan/**; use repository-relative paths, branch names, PR numbers...".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md` around lines 7 - 8, The trace includes a local worktree directory name (GFramework-WorkTree/GFramework-input-system-godot-integration); replace that environment-specific path with a stable identifier composed of the branch name (feat/input-system-godot-integration) and the PR number (e.g., "feat/input-system-godot-integration#NNN") in the file ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md so the record uses repository-relative, non-sensitive identifiers instead of machine-specific directories.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@GFramework.Game.Abstractions/README.md`:
- Line 180: The README currently lists "Input/" as an entry point but doesn't
include the corresponding docs link; update the "对应文档入口" section in
GFramework.Game.Abstractions/README.md to add an entry pointing to
docs/zh-CN/game/input.md so the module README lists the matching docs. Make sure
the "Input/" row or bullet references docs/zh-CN/game/input.md alongside the
existing symbols (`Input/`, `InputBindingDescriptor`, `IInputBindingStore`,
`IInputDeviceTracker`, `IUiInputDispatcher`) so navigation is complete.
In `@GFramework.Game/Input/InputBindingStore.cs`:
- Around line 31-35: GetBindings currently calls GetOrCreateBindings which
implicitly creates an entry during a read and causes empty entries to be
exported by ExportSnapshot; change GetBindings so it does a read-only lookup
(e.g., use the underlying dictionary.TryGetValue or a new TryGetBindings helper)
instead of calling GetOrCreateBindings, and return an InputActionBinding with an
empty array when no bindings exist. Ensure you only reference GetBindings and
InputActionBinding (and ExportSnapshot semantics remain intact) and do not
mutate the store during this method.
In `@GFramework.Game/Input/InputDeviceTracker.cs`:
- Around line 22-31: The XML docs for Update and CurrentDevice lack
thread-safety guidance; either document that Update must be called only from the
host/input thread (e.g., Godot's main/input event thread) by adding a <remarks>
to the Update method and to CurrentDevice explaining the required calling
thread, or make CurrentDevice a volatile field/property to ensure cross-thread
visibility and document that choice in the XML docs (mentioning that volatile
provides write-read visibility but does not provide higher-level
synchronization). Update the XML comments on the Update method and the
CurrentDevice member to state which approach you chose and the expected
synchronization semantics so callers know how to safely access them.
In `@GFramework.Game/Input/UiInputDispatcher.cs`:
- Around line 17-26: The constructor UiInputDispatcher(IUiInputActionMap
actionMap, IUiRouter router) performs null checks and throws
ArgumentNullException for actionMap and router but the XML doc lacks <exception>
entries; update the constructor's XML documentation to include two <exception
cref="System.ArgumentNullException"> tags describing when actionMap and router
are null (reference the parameter names in the descriptions) so the thrown
exceptions are documented.
In `@GFramework.Game/README.md`:
- Around line 162-177: README.md is missing a top-level link to the new Input
subsystem; add an entry to the README's main "文档入口" list pointing to the 输入系统
docs at ../docs/zh-CN/game/input.md so the module README and docs entry points
are consistent. Locate the README's summary/list of subsystem links and append
or insert a line referencing "输入系统 (Input)" that corresponds to the Input folder
and symbols InputBindingStore, InputDeviceTracker, UiInputActionMap,
UiInputDispatcher to satisfy the rule that a module README must reference its
docs/zh-CN entry.
In `@GFramework.Godot/Input/GodotInputBindingStore.cs`:
- Around line 59-68: ImportSnapshot currently only updates actions present in
the snapshot and leaves any old backend bindings intact; change ImportSnapshot
(which calls ReloadFromBackend and ApplyActionBindings) to perform a
snapshot-level replace by: after reloading backend, enumerate the current stored
action IDs, compute the set difference with snapshot.Actions, and remove/clear
bindings for any actions not present in the snapshot (use or add a
backend-facing helper such as RemoveActionBindings/RemoveAction or
ClearBindingsForAction as appropriate), then apply bindings for each action in
snapshot via ApplyActionBindings so the store exactly matches the snapshot.
In `@GFramework.Godot/Input/GodotInputMapBackend.cs`:
- Around line 33-37: GetBindings currently calls InputMap.ActionGetEvents
without validating the incoming actionName; update GetBindings to validate the
parameter (null/empty) and check existence with InputMap.HasAction(actionName)
and if the action does not exist return an empty
IReadOnlyList<InputBindingDescriptor> immediately, avoiding calling
InputMap.ActionGetEvents or passing invalid input to host APIs; locate this
logic in the GetBindings method and mirror the same parameter checks used in
SetBindings/ResetAction.
---
Nitpick comments:
In
`@ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md`:
- Around line 7-8: The trace includes a local worktree directory name
(GFramework-WorkTree/GFramework-input-system-godot-integration); replace that
environment-specific path with a stable identifier composed of the branch name
(feat/input-system-godot-integration) and the PR number (e.g.,
"feat/input-system-godot-integration#NNN") in the file
ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md
so the record uses repository-relative, non-sensitive identifiers instead of
machine-specific directories.
In `@GFramework.Game.Abstractions/Input/InputActionBinding.cs`:
- Around line 9-26: Convert the immutable snapshot class InputActionBinding to a
record to get value semantics consistent with other snapshots (e.g.,
InputBindingSnapshot): change the declaration from class to a record (e.g.,
public sealed record InputActionBinding) and keep the existing constructor logic
that validates actionName and assigns Bindings (falling back to
Array.Empty<InputBindingDescriptor>() when null); preserve the XML doc comments
for the type and parameters, and ensure the public members ActionName and
Bindings remain available (init-only or positional record properties) so
existing callers continue to work.
In `@GFramework.Game.Abstractions/Input/InputBindingDescriptor.cs`:
- Around line 13-41: Convert the immutable data class InputBindingDescriptor
into a record with the same public API: change InputBindingDescriptor to a
public sealed record that exposes DeviceKind, BindingKind, Code, DisplayName and
AxisDirection as init-only properties (or positional parameters) while
preserving the constructor validation that throws ArgumentException when Code is
null/whitespace, preserve the default DisplayName -> string.Empty and nullable
AxisDirection behavior, and keep the existing XML doc comments; ensure
equality/value semantics and ToString come from the record type and that any
callers using the old constructor still get the validation logic.
In `@GFramework.Game.Abstractions/Input/InputBindingSnapshot.cs`:
- Around line 9-23: Replace the class InputBindingSnapshot with a record to give
it value semantics: change the declaration to a record type named
InputBindingSnapshot while preserving the existing XML documentation comments;
ensure the Actions property remains an IReadOnlyList<InputActionBinding> and
that the constructor logic (or primary constructor) still defaults null to
Array.Empty<InputActionBinding>() so existing behavior and immutability are
preserved; keep the public API (type name and property) unchanged so comparisons
and serialization benefit from record semantics.
In `@GFramework.Game.Abstractions/Input/InputDeviceContext.cs`:
- Around line 9-25: InputDeviceContext is an immutable value object so change
the class to a record to get value semantics; replace the sealed class
declaration with a record (e.g., record InputDeviceContext) and expose the same
data via init-only properties or a positional record matching the existing
constructor parameters (DeviceKind, int? DeviceIndex, string? DeviceName) while
preserving the XML documentation comments for the constructor/parameters and
retaining the DeviceKind, DeviceIndex and DeviceName identifiers and
null-handling (DeviceName defaulting to string.Empty) so
Equals/GetHashCode/ToString behave as value semantics.
In `@GFramework.Godot/Input/IGodotInputMapBackend.cs`:
- Around line 11-43: Add clear precondition docs to the interface: state that
actionName for GetBindings, SetBindings, ResetAction must be non-null and
non-empty and that SetBindings' bindings parameter must be non-null (and may be
empty) and that GetActionNames/ GetBindings return IReadOnlyList that will never
be null; also specify whether implementations should throw
ArgumentNullException/ArgumentException on violation or silently ignore—e.g.,
document to throw ArgumentNullException for null actionName and
ArgumentException for empty names, and ArgumentNullException for null bindings
in SetBindings. Update the XML comments for GetBindings, SetBindings,
ResetAction, and ResetAll to include these precondition sentences and the
expected exceptions so implementers and callers know validation responsibility.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 142798c2-190a-4d24-96b9-8c10574177cd
📒 Files selected for processing (32)
GFramework.Game.Abstractions/Input/IInputBindingStore.csGFramework.Game.Abstractions/Input/IInputDeviceTracker.csGFramework.Game.Abstractions/Input/IUiInputActionMap.csGFramework.Game.Abstractions/Input/IUiInputDispatcher.csGFramework.Game.Abstractions/Input/InputActionBinding.csGFramework.Game.Abstractions/Input/InputBindingDescriptor.csGFramework.Game.Abstractions/Input/InputBindingKind.csGFramework.Game.Abstractions/Input/InputBindingSnapshot.csGFramework.Game.Abstractions/Input/InputDeviceContext.csGFramework.Game.Abstractions/Input/InputDeviceKind.csGFramework.Game.Abstractions/README.mdGFramework.Game.Tests/Input/InputBindingStoreTests.csGFramework.Game.Tests/Input/UiInputDispatcherTests.csGFramework.Game/Input/InputBindingStore.csGFramework.Game/Input/InputDeviceTracker.csGFramework.Game/Input/UiInputActionMap.csGFramework.Game/Input/UiInputDispatcher.csGFramework.Game/README.mdGFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Godot/Input/GodotInputBindingCodec.csGFramework.Godot/Input/GodotInputBindingStore.csGFramework.Godot/Input/GodotInputMapBackend.csGFramework.Godot/Input/IGodotInputMapBackend.csGFramework.Godot/README.mdai-plan/public/README.mdai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.mdai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.mddocs/zh-CN/game/index.mddocs/zh-CN/game/input.mddocs/zh-CN/godot/index.mddocs/zh-CN/godot/input.mddocs/zh-CN/tutorials/godot-integration.md
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Code Quality & Security
- GitHub Check: Build and Test
- GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (13)
**/*Abstractions/**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
Abstractions projects should only contain interfaces and contract definitions without any runtime implementation logic
Files:
GFramework.Game.Abstractions/Input/InputDeviceKind.csGFramework.Game.Abstractions/Input/IUiInputDispatcher.csGFramework.Game.Abstractions/Input/IInputBindingStore.csGFramework.Game.Abstractions/Input/InputBindingDescriptor.csGFramework.Game.Abstractions/Input/InputBindingSnapshot.csGFramework.Game.Abstractions/Input/IInputDeviceTracker.csGFramework.Game.Abstractions/Input/InputBindingKind.csGFramework.Game.Abstractions/Input/IUiInputActionMap.csGFramework.Game.Abstractions/Input/InputDeviceContext.csGFramework.Game.Abstractions/Input/InputActionBinding.cs
**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic
**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///)
XML documentation comments MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, explaining intent, contract, and usage constraints instead of restating syntax
If a member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly in XML documentation
Add inline comments for non-trivial logic, concurrency or threading behavior, performance-sensitive paths, workarounds and compatibility constraints, edge cases, registration order, lifecycle sequencing, and generated code assumptions
Avoid obvious comments such as// increment i
Methods with non-trivial logic MUST document: The core idea, Key decisions, and Edge case handling, if any
Comments MUST NOT be trivial, redundant, or misleading. Prefer explainingwhyandwhen, not justwhat. Code should remain understandable without requiring external context. Prefer slightly more explanation over too little for framework code
Do not rely on implicit imports. Declare every requiredusingexplicitly
Write null-safe code that respects nullable annotations instead of suppressing warnings by default
Use the namespace patternGFramework.{Module}.{Feature}with PascalCase segments
Follow standard C# naming: Types, methods, properties, events, and constants use PascalCase; Interfaces useIprefix; Parameters and locals use camelCase; Private fields use_camelCase
Use 4 spaces for indentation. Do not use tabs
Use Allman braces
Keepusingdirectives at the top...
Files:
GFramework.Game.Abstractions/Input/InputDeviceKind.csGFramework.Game.Abstractions/Input/IUiInputDispatcher.csGFramework.Game/Input/UiInputActionMap.csGFramework.Game/Input/InputDeviceTracker.csGFramework.Game.Abstractions/Input/IInputBindingStore.csGFramework.Game.Abstractions/Input/InputBindingDescriptor.csGFramework.Game/Input/UiInputDispatcher.csGFramework.Game.Abstractions/Input/InputBindingSnapshot.csGFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Game.Abstractions/Input/IInputDeviceTracker.csGFramework.Game.Abstractions/Input/InputBindingKind.csGFramework.Game.Abstractions/Input/IUiInputActionMap.csGFramework.Game.Tests/Input/UiInputDispatcherTests.csGFramework.Game.Abstractions/Input/InputDeviceContext.csGFramework.Game.Abstractions/Input/InputActionBinding.csGFramework.Godot/Input/GodotInputBindingCodec.csGFramework.Game.Tests/Input/InputBindingStoreTests.csGFramework.Godot/Input/IGodotInputMapBackend.csGFramework.Godot/Input/GodotInputMapBackend.csGFramework.Godot/Input/GodotInputBindingStore.csGFramework.Game/Input/InputBindingStore.cs
**/README.md
📄 CodeRabbit inference engine (AGENTS.md)
**/README.md: Use the canonical filenameREADME.md. Do not introduce newReadMe.mdor other filename variants
A module README MUST describe: the module's purpose, the relationship to adjacent runtime, abstractions, or generator packages, the major subdirectories or subsystems the reader is expected to use, the minimum adoption path, and the correspondingdocs/zh-CN/entry points
If a module's responsibilities, setup, public API surface, generator inputs, or adoption path change, update that module'sREADME.mdin the same change
Files:
ai-plan/public/README.mdGFramework.Game.Abstractions/README.mdGFramework.Game/README.mdGFramework.Godot/README.md
ai-plan/public/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/public/**: Contributors MUST keep committedai-plan/public/**content safe to publish in Git history
Active tracking and trace files are recovery entrypoints, not append-only changelogs. They MUST stay concise enough forbootto locate the current recovery point quickly
When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the activetodos/andtraces/entry files in the same change. Keep only the current recovery point, active facts, active risks, immediate next step, and pointers to the relevant archive files in the default boot path
When a topic is fully complete, move the entire topic directory underai-plan/public/archive/<topic>/and remove it fromai-plan/public/README.mdin the same change
When a task spans multiple commits or is likely to exceed a single agent context window, update both the recovery document and the trace at each meaningful milestone before pausing or handing work off
If subagents are used on a complex task, the main agent MUST capture the delegated scope and any accepted findings in the active recovery document or trace before continuing implementation
Files:
ai-plan/public/README.mdai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.mdai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md
ai-plan/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/**: Never write secrets, tokens, credentials, private keys, machine usernames, home-directory paths, hostnames, IP addresses, proprietary URLs, or other sensitive environment details into anyai-plan/**file
Never record absolute file-system paths inai-plan/**; use repository-relative paths, branch names, PR numbers, or stable document identifiers instead
Files:
ai-plan/public/README.mdai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.mdai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md
ai-plan/public/README.md
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/public/README.md:ai-plan/public/README.mdMUST list only active topics. Do not addai-plan/public/archive/**content to the default boot index
When a worktree-to-topic mapping changes, or when a topic becomes active/inactive, contributors MUST updateai-plan/public/README.mdin the same change
Files:
ai-plan/public/README.md
ai-plan/public/**/traces/**
📄 CodeRabbit inference engine (AGENTS.md)
Contributors MUST maintain a matching execution trace under
ai-plan/public/<topic>/traces/for complex work. The trace should record the current date, key decisions, validation milestones, and the immediate next step
Files:
ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md
docs/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Documentation should be organized with Chinese content in docs/zh-CN/ and structured to include getting started, module-specific capabilities (Core, Game, Godot, ECS), source generator usage, tutorials, best practices, and troubleshooting
Files:
docs/zh-CN/tutorials/godot-integration.mddocs/zh-CN/game/index.mddocs/zh-CN/godot/input.mddocs/zh-CN/godot/index.mddocs/zh-CN/game/input.md
{README.md,docs/**}
📄 CodeRabbit inference engine (AGENTS.md)
{README.md,docs/**}: Update the relevantREADME.mdordocs/page when behavior, setup steps, architecture guidance, or user-facing examples change
Public documentation underREADME.mdanddocs/MUST stay reader-facing. Do not publish governance-only content such as inventory tables, coverage baselines, review queues, batch metrics, recovery points, trace summaries, or "this still needs a later audit wave" notes
Public documentation MUST use semantic section titles and link labels. Do not surface raw filenames or paths such asREADME.md、game/index.md、../core/cqrs.mdas reader-facing navigation text when a meaningful destination label is available
Public documentation MUST avoid rhetorical, self-referential, or AI-sounding headings and prompts. Prefer neutral labels instead of phrases like "你真正会用到的公开入口"、"先理解包关系"、"这个栏目应该回答什么" or "想看……转到……"
Public documentation MUST present limitations, suitability, and migration boundaries as adoption guidance for readers. Do not publish internal-governance or product-roadmap wording inREADME.mdordocs/**; that material belongs inai-plan/**
Files:
docs/zh-CN/tutorials/godot-integration.mddocs/zh-CN/game/index.mddocs/zh-CN/godot/input.mddocs/zh-CN/godot/index.mddocs/zh-CN/game/input.md
docs/**
📄 CodeRabbit inference engine (AGENTS.md)
docs/**: The main documentation site lives underdocs/, with Chinese content underdocs/zh-CN/
Keep code samples, package names, and command examples aligned with the current repository state
Prefer documenting behavior and design intent, not only API surface
When a public page references XML docs or API coverage, convert that evidence into reader-facing guidance: explain which types, namespaces, or entry points readers should inspect and why, instead of exposing audit counts or governance terminology
If an existing documentation page no longer reflects the current implementation, fixing the code without fixing the documentation is considered incomplete work
Do not rely on "the code is self-explanatory" for framework features that consumers need to adopt; write the adoption path down so future users do not need to rediscover it from source
When examples are rewritten, preserve only the parts that remain true. Delete or replace speculative examples instead of lightly editing them into another inaccurate form
Files:
docs/zh-CN/tutorials/godot-integration.mddocs/zh-CN/game/index.mddocs/zh-CN/godot/input.mddocs/zh-CN/godot/index.mddocs/zh-CN/game/input.md
docs/zh-CN/**
📄 CodeRabbit inference engine (AGENTS.md)
docs/zh-CN/**: When a feature is added, removed, renamed, or substantially refactored, contributors MUST update or create the corresponding user-facing integration documentation indocs/zh-CN/in the same change
For integration-oriented features such as the AI-First config system, documentation MUST cover: project directory layout and file conventions, required project or package wiring, minimal working usage example, and migration or compatibility notes when behavior changes
Files:
docs/zh-CN/tutorials/godot-integration.mddocs/zh-CN/game/index.mddocs/zh-CN/godot/input.mddocs/zh-CN/godot/index.mddocs/zh-CN/game/input.md
**/*.Tests/**/*.cs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.Tests/**/*.cs: Mirror the source structure in test projects whenever practical
Reuse existing architecture test infrastructure when relevant:ArchitectureTestsBase<T>,SyncTestArchitecture,AsyncTestArchitecture
Files:
GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Game.Tests/Input/UiInputDispatcherTests.csGFramework.Game.Tests/Input/InputBindingStoreTests.cs
ai-plan/public/**/todos/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/public/**/todos/**: When working from a tracked implementation plan, contributors MUST update the corresponding tracking document underai-plan/public/<topic>/todos/in the same change
Tracking updates MUST reflect completed work, newly discovered issues, validation results, and the next recommended recovery point
For any multi-step refactor, migration, or cross-module task, contributors MUST create or adopt a dedicated recovery document underai-plan/public/<topic>/todos/before making substantive code changes
Recovery documents MUST record the current phase, the active recovery point identifier, known risks, and the next recommended resume step so another contributor or subagent can continue the work safely
Files:
ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md
🧠 Learnings (1)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.
Applied to files:
GFramework.Game.Abstractions/Input/InputDeviceKind.csGFramework.Game.Abstractions/Input/IUiInputDispatcher.csGFramework.Game/Input/UiInputActionMap.csGFramework.Game/Input/InputDeviceTracker.csGFramework.Game.Abstractions/Input/IInputBindingStore.csGFramework.Game.Abstractions/Input/InputBindingDescriptor.csGFramework.Game/Input/UiInputDispatcher.csGFramework.Game.Abstractions/Input/InputBindingSnapshot.csGFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Game.Abstractions/Input/IInputDeviceTracker.csGFramework.Game.Abstractions/Input/InputBindingKind.csGFramework.Game.Abstractions/Input/IUiInputActionMap.csGFramework.Game.Tests/Input/UiInputDispatcherTests.csGFramework.Game.Abstractions/Input/InputDeviceContext.csGFramework.Game.Abstractions/Input/InputActionBinding.csGFramework.Godot/Input/GodotInputBindingCodec.csGFramework.Game.Tests/Input/InputBindingStoreTests.csGFramework.Godot/Input/IGodotInputMapBackend.csGFramework.Godot/Input/GodotInputMapBackend.csGFramework.Godot/Input/GodotInputBindingStore.csGFramework.Game/Input/InputBindingStore.cs
🔇 Additional comments (12)
ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md (1)
1-49: 跟踪文档结构完整,符合恢复点规范。该跟踪文档正确定义了恢复点编号(
INPUT-GODOT-RP-001)、当前阶段、状态摘要、风险缓解措施、验证命令以及下一步行动,内容简洁且适合作为boot入口快速定位当前进度。验证命令使用相对路径且不包含敏感信息,符合ai-plan安全发布要求。GFramework.Game.Abstractions/Input/IUiInputActionMap.cs (1)
1-21: 接口定义清晰,文档完整。
IUiInputActionMap接口职责明确,仅定义逻辑动作名到 UI 语义动作的映射契约,符合抽象层设计原则。XML 文档包含完整的<summary>、<param>和<returns>标签,清楚说明了映射语义。GFramework.Game.Abstractions/Input/InputBindingKind.cs (1)
1-36: 枚举定义合理,覆盖常见输入绑定类型。
InputBindingKind枚举清晰定义了键盘按键、鼠标按钮、手柄按钮和手柄轴向等主要输入类型,每个成员都配有 XML 文档说明。Unknown = 0作为默认值符合最佳实践。GFramework.Game.Abstractions/Input/IUiInputDispatcher.cs (1)
1-18: 输入分发契约设计简洁有效。
IUiInputDispatcher接口通过单一职责的TryDispatch方法定义了输入动作到 UI 路由的桥接契约,返回值语义明确(映射成功且分发成功时返回true),XML 文档完整。GFramework.Game.Abstractions/Input/InputDeviceKind.cs (1)
1-35: 设备族枚举设计合理,文档详尽。
InputDeviceKind枚举定义了跨宿主的输入设备族分类,<remarks>部分清楚说明了该抽象的设计意图(避免暴露引擎原生类型,确保上层业务依赖稳定的设备族判断),这种对设计动机的明确记录值得肯定。ai-plan/public/README.md (1)
41-44: 公共索引更新正确,与新增主题同步。新增的
input-system-godot-integration活跃主题条目包含完整的目的说明、跟踪文档和追踪文档链接,同时在 Worktree 映射中正确注册了对应分支,格式与现有条目保持一致,符合ai-plan治理规范。Also applies to: 62-64
GFramework.Game/Input/UiInputActionMap.cs (1)
1-40: 默认映射实现简洁高效。
UiInputActionMap实现正确处理了空值/空白字符串输入(第 31 行),使用StringComparer.OrdinalIgnoreCase实现大小写不敏感匹配,并通过静态只读字典提供了合理的默认别名集(兼容 Godotui_*命名约定)。<remarks>部分明确说明了可通过自定义实现扩展映射表的能力。GFramework.Game/Input/UiInputDispatcher.cs (1)
28-37: 分发逻辑实现正确,职责清晰。
TryDispatch方法正确实现了"映射失败时提前返回false,映射成功时将结果转发给 UI 路由器"的桥接语义,逻辑简洁且符合单一职责原则。GFramework.Game.Tests/Input/UiInputDispatcherTests.cs (1)
1-52: 测试覆盖合理且结构清晰测试用例覆盖了映射成功和未知动作两种场景,使用
Assert.Multiple提高了断言的可读性,Mock 验证逻辑正确。实现符合 NUnit 最佳实践。GFramework.Game.Abstractions/Input/IInputDeviceTracker.cs (1)
1-15: 接口设计清晰单一职责接口,仅公开只读的
CurrentDevice属性,符合抽象层的设计原则。XML 文档注释充分说明了契约语义。GFramework.Game.Abstractions/Input/InputBindingDescriptor.cs (1)
31-34: 验证逻辑正确对
code参数进行非空白验证是恰当的,因为它是绑定的核心标识符。异常类型和消息清晰明确。GFramework.Game.Abstractions/Input/InputActionBinding.cs (1)
19-22: 验证逻辑正确对
actionName的非空白验证是必要的,确保了动作绑定始终有有效的标识符。
- 修复 InputBindingStore 只读查询会污染导出快照的问题 - 修复 Godot 输入绑定导入时未清理残留动作绑定的问题 - 补充输入运行时与 Godot backend 的 XML 契约说明和 README 入口 - 更新 ai-plan 跟踪并补充针对 PR #346 的回归测试
Summary
Test ResultsDetails
Insights
build-and-test: Run #1103
🎉 All tests passed!Slowest Tests
± Comparison with run #1102 at 4026ee3 | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 2 runs. Github Test Reporter by CTRF 💚 |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md (1)
46-47: 验证结果待补录。第 47 行的 license-header 检查结果标记为"待本轮验证补录"。
是否需要我生成验证脚本来完成此项检查并补录结果?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md` around lines 46 - 47, The TODO entry shows the license-header check result as "待本轮验证补录"—fix by running the exact command shown (`python3 scripts/license-header.py --check --paths GFramework.Game.Abstractions/README.md GFramework.Game.Tests/Input/InputBindingStoreTests.cs GFramework.Game/Input/InputBindingStore.cs GFramework.Game/Input/InputDeviceTracker.cs GFramework.Game/Input/UiInputDispatcher.cs GFramework.Game/README.md GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.cs GFramework.Godot/Input/GodotInputBindingStore.cs GFramework.Godot/Input/GodotInputMapBackend.cs GFramework.Godot/Input/IGodotInputMapBackend.cs ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md`), capture the CLI output (pass/fail and any file list), and update the markdown entry in input-system-godot-integration-tracking.md by replacing the "待本轮验证补录" marker with the actual verification result and any relevant failing filenames or error messages from the command; if you prefer automation, add a small verification script that runs that command and writes the formatted result back into the same markdown entry.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md`:
- Around line 46-47: The TODO entry shows the license-header check result as
"待本轮验证补录"—fix by running the exact command shown (`python3
scripts/license-header.py --check --paths GFramework.Game.Abstractions/README.md
GFramework.Game.Tests/Input/InputBindingStoreTests.cs
GFramework.Game/Input/InputBindingStore.cs
GFramework.Game/Input/InputDeviceTracker.cs
GFramework.Game/Input/UiInputDispatcher.cs GFramework.Game/README.md
GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.cs
GFramework.Godot/Input/GodotInputBindingStore.cs
GFramework.Godot/Input/GodotInputMapBackend.cs
GFramework.Godot/Input/IGodotInputMapBackend.cs
ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md`),
capture the CLI output (pass/fail and any file list), and update the markdown
entry in input-system-godot-integration-tracking.md by replacing the "待本轮验证补录"
marker with the actual verification result and any relevant failing filenames or
error messages from the command; if you prefer automation, add a small
verification script that runs that command and writes the formatted result back
into the same markdown entry.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 457c4f2e-cbb5-4f16-981d-70cf279026b6
📒 Files selected for processing (12)
GFramework.Game.Abstractions/README.mdGFramework.Game.Tests/Input/InputBindingStoreTests.csGFramework.Game/Input/InputBindingStore.csGFramework.Game/Input/InputDeviceTracker.csGFramework.Game/Input/UiInputDispatcher.csGFramework.Game/README.mdGFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Godot/Input/GodotInputBindingStore.csGFramework.Godot/Input/GodotInputMapBackend.csGFramework.Godot/Input/IGodotInputMapBackend.csai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.mdai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md
✅ Files skipped from review due to trivial changes (2)
- GFramework.Game/README.md
- GFramework.Game.Abstractions/README.md
🚧 Files skipped from review as they are similar to previous changes (6)
- GFramework.Game/Input/UiInputDispatcher.cs
- GFramework.Game/Input/InputDeviceTracker.cs
- GFramework.Godot/Input/IGodotInputMapBackend.cs
- GFramework.Godot/Input/GodotInputBindingStore.cs
- GFramework.Godot/Input/GodotInputMapBackend.cs
- GFramework.Game/Input/InputBindingStore.cs
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Code Quality & Security
- GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic
**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///)
XML documentation comments MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, explaining intent, contract, and usage constraints instead of restating syntax
If a member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly in XML documentation
Add inline comments for non-trivial logic, concurrency or threading behavior, performance-sensitive paths, workarounds and compatibility constraints, edge cases, registration order, lifecycle sequencing, and generated code assumptions
Avoid obvious comments such as// increment i
Methods with non-trivial logic MUST document: The core idea, Key decisions, and Edge case handling, if any
Comments MUST NOT be trivial, redundant, or misleading. Prefer explainingwhyandwhen, not justwhat. Code should remain understandable without requiring external context. Prefer slightly more explanation over too little for framework code
Do not rely on implicit imports. Declare every requiredusingexplicitly
Write null-safe code that respects nullable annotations instead of suppressing warnings by default
Use the namespace patternGFramework.{Module}.{Feature}with PascalCase segments
Follow standard C# naming: Types, methods, properties, events, and constants use PascalCase; Interfaces useIprefix; Parameters and locals use camelCase; Private fields use_camelCase
Use 4 spaces for indentation. Do not use tabs
Use Allman braces
Keepusingdirectives at the top...
Files:
GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Game.Tests/Input/InputBindingStoreTests.cs
**/*.Tests/**/*.cs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.Tests/**/*.cs: Mirror the source structure in test projects whenever practical
Reuse existing architecture test infrastructure when relevant:ArchitectureTestsBase<T>,SyncTestArchitecture,AsyncTestArchitecture
Files:
GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Game.Tests/Input/InputBindingStoreTests.cs
ai-plan/public/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/public/**: Contributors MUST keep committedai-plan/public/**content safe to publish in Git history
Active tracking and trace files are recovery entrypoints, not append-only changelogs. They MUST stay concise enough forbootto locate the current recovery point quickly
When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the activetodos/andtraces/entry files in the same change. Keep only the current recovery point, active facts, active risks, immediate next step, and pointers to the relevant archive files in the default boot path
When a topic is fully complete, move the entire topic directory underai-plan/public/archive/<topic>/and remove it fromai-plan/public/README.mdin the same change
When a task spans multiple commits or is likely to exceed a single agent context window, update both the recovery document and the trace at each meaningful milestone before pausing or handing work off
If subagents are used on a complex task, the main agent MUST capture the delegated scope and any accepted findings in the active recovery document or trace before continuing implementation
Files:
ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.mdai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md
ai-plan/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/**: Never write secrets, tokens, credentials, private keys, machine usernames, home-directory paths, hostnames, IP addresses, proprietary URLs, or other sensitive environment details into anyai-plan/**file
Never record absolute file-system paths inai-plan/**; use repository-relative paths, branch names, PR numbers, or stable document identifiers instead
Files:
ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.mdai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md
ai-plan/public/**/todos/**
📄 CodeRabbit inference engine (AGENTS.md)
ai-plan/public/**/todos/**: When working from a tracked implementation plan, contributors MUST update the corresponding tracking document underai-plan/public/<topic>/todos/in the same change
Tracking updates MUST reflect completed work, newly discovered issues, validation results, and the next recommended recovery point
For any multi-step refactor, migration, or cross-module task, contributors MUST create or adopt a dedicated recovery document underai-plan/public/<topic>/todos/before making substantive code changes
Recovery documents MUST record the current phase, the active recovery point identifier, known risks, and the next recommended resume step so another contributor or subagent can continue the work safely
Files:
ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md
ai-plan/public/**/traces/**
📄 CodeRabbit inference engine (AGENTS.md)
Contributors MUST maintain a matching execution trace under
ai-plan/public/<topic>/traces/for complex work. The trace should record the current date, key decisions, validation milestones, and the immediate next step
Files:
ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md
🧠 Learnings (1)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.
Applied to files:
GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.csGFramework.Game.Tests/Input/InputBindingStoreTests.cs
🪛 LanguageTool
ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md
[grammar] ~16-~16: Ensure spelling is correct
Context: ...ts的新增回归,并补docs/zh-CN/game/input.md与docs/zh-CN/godot/input.md - 已处理 PR#346` 的首轮 review follow-up,修复只读查询污染...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md
[uncategorized] ~73-~73: 您的意思是“"不"录”?
Context: ...# 下一步 1. 运行针对本次改动文件的 license-header 检查并补录结果 2. 如需继续消化 PR review,再单独评估值对象切换到 `rec...
(BU)
🔇 Additional comments (4)
ai-plan/public/input-system-godot-integration/traces/input-system-godot-integration-trace.md (1)
1-75: 追踪文档结构清晰,符合规范。该追踪文档正确记录了 2026-05-11 针对 PR
#346的 review follow-up,包含:
- 明确的恢复点标识(RP-001)
- 核心问题清单与修复决策
- 新增回归测试的验证结果
- 清晰的下一步行动项
文档符合
ai-plan/public/**/traces/**的要求,保持简洁并聚焦当前恢复点。ai-plan/public/input-system-godot-integration/todos/input-system-godot-integration-tracking.md (1)
1-55: 跟踪文档结构完整,恢复点清晰。该跟踪文档正确实现了
ai-plan/public/**/todos/**的要求:
- 明确的恢复点编号(INPUT-GODOT-RP-001)与当前阶段(Phase 1)
- 完整的目标、状态、风险与验证说明
- 清晰的下一步行动建议
文档聚焦当前恢复点,便于后续恢复或移交工作。
GFramework.Game.Tests/Input/InputBindingStoreTests.cs (1)
1-96: 测试覆盖全面,结构清晰。该测试文件正确实现了对
InputBindingStore的行为验证:
- 绑定冲突时的交换语义
- 重置操作恢复默认快照
- 查询缺失动作时不污染快照(新增回归测试)
所有测试方法均包含清晰的 XML 文档说明,使用
Assert.Multiple组织相关断言,符合 NUnit 最佳实践。GFramework.Godot.Tests/Input/GodotInputBindingStoreTests.cs (1)
1-258: 测试覆盖完整,FakeInputMapBackend实现清晰。该测试文件正确验证了
GodotInputBindingStore的核心行为:
- 快照导出反映后端绑定
- 快照导入更新后端绑定
- 导入快照时清空缺失动作的后端绑定(新增回归测试,lines 88-140)
- 主绑定设置时保留冲突交换语义
FakeInputMapBackend(lines 196-256)提供了确定性的测试桩实现,正确分离了默认绑定与当前绑定的状态管理,使测试场景可重复验证。
- 修复 InputBindingStore 的线程安全使用说明并消除 GodotInputBindingCodec 的重复键码计算\n- 修复 GodotInputMapBackend 在全量重置时未移除运行时新增动作的语义偏差并补回归测试\n- 更新 input-system-godot-integration 的 tracking 与 trace,补录 PR review follow-up 验证结果
Summary
Test ResultsDetails
Insights
build-and-test: Run #1105
🎉 All tests passed!Slowest Tests
± Comparison with run #1103 at a7cae5d | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 3 runs. Github Test Reporter by CTRF 💚 |
新增输入绑定 DTO、设备上下文和 UI 语义桥接契约。
实现 Game 默认输入绑定存储、动作映射和 UI 分发桥接。
落地 Godot InputMap 适配、测试覆盖与配套文档。
更新 ai-plan 恢复点、worktree 映射与采用入口。
Summary by CodeRabbit
发布说明
New Features
Tests
Documentation